#! /usr/bin/env python

import sys
import os
from optparse import OptionParser
#head format
# 8 ascii : version of this data format (0)
# 80 ascii : local patient identification
# 80 ascii : local recording identification
# 8 ascii : startdate of recording (dd.mm.yy)
# 8 ascii : starttime of recording (hh.mm.ss)
# 8 ascii : number of bytes in header record
# 44 ascii : reserved
# 8 ascii : number of data records (-1 if unknown)
# 8 ascii : duration of a data record, in seconds
# 4 ascii : number of signals (ns) in data record
# ns * 16 ascii : ns * label (e.g. EEG FpzCz or Body temp)
# ns * 80 ascii : ns * transducer type (e.g. AgAgCl electrode)
# ns * 8 ascii : ns * physical dimension (e.g. uV or degreeC)
# ns * 8 ascii : ns * physical minimum (e.g. -500 or 34)
# ns * 8 ascii : ns * physical maximum (e.g. 500 or 40)
# ns * 8 ascii : ns * digital minimum (e.g. -2048)
# ns * 8 ascii : ns * digital maximum (e.g. 2047)
# ns * 80 ascii : ns * prefiltering (e.g. HP:0.1Hz LP:75Hz)
# ns * 8 ascii : ns * nr of samples in each data record
# ns * 32 ascii : ns * reserved

# DATA RECORD
# one record after record
# nr of samples[1] * integer : first signal in the data record
# nr of samples[2] * integer : second signal
# ..
# ..
# nr of samples[ns] * integer : last signal
filepath = os.path.abspath(os.path.dirname(__file__))
scriptpath = os.path.dirname(filepath)
sys.path.append(scriptpath)

from config import DATA_PATH, FRAME_DATA_PATH
#print DATA_PATH
#DATA_PATH = '/home/linxj/Documents/data/raw_data/web_sleep'
#FRAME_DATA_PATH = '/home/linxj/Documents/data/frame_data/'
head = {'version': '',
        'petientID': '', 'recordID': '', 
        'startDate': '', 'startTime': '', 
        'headLenthByte': '', 'reserved': '', 
        'NumOfRecords': '', 'secondsPerRecord': '', 'NumOfSignals': '',
        'labels': '', 'transducerType': '', 
        'physicalDimension': '', 'physicalMinimum': '', 'physicalMaximum': '',
        'digitalMinimum': '', 'digitalMaximum': '',
        'preFiltering': '',
        'samples': '', 
        'tailReserved': '' }
record = {}
ns = 0
nr = 0
labels = []
samples = []
scalfc = []
dc = []
keylist = [ 'version', 
            'petientID', 'recordID', 
            'startDate', 'startTime', 
            'headLenthByte', 'reserved', 
            'NumOfRecords', 'secondsPerRecord' 'NumOfSignals',
            'labels', 'transducerType', 
            'physicalDimension', 'physicalMinimum', 'physicalMaximum',
            'digitalMinimum', 'digitalMaximum',
            'preFiltering',
            'samples', 
            'tailReserved']


def headPaser(filename):
    """
    @filename 'test.edf'
    @head dict      
    """
    print "headPaser"
    global ns
    global nr
    f = open(filename,'r')
    head['version'] = f.read(8)
    head['petientID'] = f.read(80)
    head['recordID'] = f.read(80)
    head['startDate'] = f.read(8)
    head['startTime'] = f.read(8)
    head['headLenthByte'] = int(f.read(8))
    head['reserved'] = f.read(44)
    head['NumOfRecords'] = int(f.read(8))

    nr = int(head['NumOfRecords']) 
    head['secondsPerRecord'] = f.read(8)
    head['NumOfSignals'] = f.read(4)
    ns = int(head['NumOfSignals']) 

    head['labels'] = f.read(16 * ns)
    strlabels = head['labels']
    labels = [strlabels[x:x+16] for x in range(0,len(strlabels),16)]

    head['labels'] = labels

    head['transducerType'] = f.read(80 * ns)
    head['physicalDimension'] = f.read(8 * ns)
    physicalDimension = head['physicalDimension']
    head['physicalDimension'] = [physicalDimension[x:x+8] for x in range(0, len(physicalDimension),8)]

    head['physicalMinimum'] = f.read(8 * ns)
    physicalMinimum = [int(x) for x in head['physicalMinimum'].split()]
    head['physicalMinimum'] = physicalMinimum
    head['physicalMaximum'] = f.read(8 * ns)
    physicalMaximum = [int(x) for x in head['physicalMaximum'].split()]
    head['physicalMaximum'] = physicalMaximum
    head['digitalMinimum'] = f.read(8 * ns)
    digitalMinimum = [int(x) for x in head['digitalMinimum'].split()]
    head['digitalMinimum'] = digitalMinimum
    head['digitalMaximum'] = f.read(8 * ns)
    digitalMaximum = [int(x) for x in head['digitalMaximum'].split()]
    head['digitalMaximum'] = digitalMaximum

    for i in range(ns):
        scanfci = float(physicalMaximum[i] - physicalMinimum[i]) / float(digitalMaximum[i] - digitalMinimum[i])
        dci = physicalMaximum[i] - scanfci*digitalMaximum[i]
        scalfc.append(scanfci)
        dc.append(dci)

    head['preFiltering'] = f.read(80 * ns)
    head['samples'] = f.read(8 * ns)
    samples = [int(x) for x in head['samples'].split()]
    head['samples'] = samples
    head['tailReserved'] = f.read(32 * ns)
    f.close()
    return 0

def str2signedint(str):
    if len(str) < 2:
        return None
    datal = ord(str[0])
    datah = ord(str[1])
    #negative data
    if datah > 127:
        return datah * 256 + datal - 65536
    else:
        return datah * 256 + datal
def getrecord(filename, name, framenumber = 1):
    print "getrecord"
    global ns
    global nr
    index = -1
    labels = head['labels']
    samples = head['samples']

    for item in labels:
        if item.find(name) >= 0:
            index = labels.index(item)
            break
    if index == -1:
         return None
    
    f = open(filename, 'r')
    
    seeki = head['headLenthByte']

    totalsamplesperrecord = 0
    for i in range(ns):
        totalsamplesperrecord += samples[i] * 2
    seeki += framenumber * totalsamplesperrecord
    
    for i in range(index):
        seeki += samples[i] * 2

    f.seek(seeki)
    datastr = f.read(samples[index] * 2)
    data = [str2signedint(datastr[x:x+2]) * scalfc[index] + dc[index] for x in range(0, len(datastr), 2)]   
    f.close()
    return data

def resultTreat(datas, resultfilename):
    print "resultTreat"
    resultfile = open(resultfilename, 'w')
    for data in datas:
        resultfile.write(str(data))
        if datas.index(data) != len(datas) - 1:
            resultfile.write('\n')
    resultfile.close()

def checkResult(filename, signal, record, count, force, sleeptype):
    if force:
        print "All record will be caculated whether or not they exists."
        print "This may take a little longer time."

    resultfiledict = {}
    existfiledict = {}
    for record_serice in range(count):
        frame_number = record + record_serice
        filename = filename.split('.')[0]
        resultname = '_'.join([filename, signal, str(frame_number)])
        if sleeptype:
            resultname = '_'.join([resultname, sleeptype])
        abs_resultname = os.path.join(FRAME_DATA_PATH, resultname)
        frame_number = str(frame_number)
        if not force:
            if os.path.exists(abs_resultname):
                existfiledict[frame_number] = abs_resultname
                print "%s exists, skip record %s, %s"% (abs_resultname, signal, frame_number)
            else:
                resultfiledict[frame_number] = abs_resultname
        else:
            resultfiledict[frame_number] = abs_resultname 
    
    print "===========exists list============"
    for frame_number in existfiledict:
        print "frame_number: %s--> %s" %(frame_number, existfiledict[frame_number])
    print "========convert list=========="
    for frame_number in resultfiledict:
        print "frame_number: %s--> %s" %(frame_number, resultfiledict[frame_number])
    
    return resultfiledict

def main():
    usage = "./converterEDF.py -f filename -s signal [options]"
    parser = OptionParser(usage = usage)
    
    parser.add_option("-f", "--file", dest="filename",
                      help="data file name")
    parser.add_option("-s", "--signal",
                      dest="signal",
                      help="signal name")
    parser.add_option("-r", "--record", dest="record",
                      type="int", default = 0,
                      help="start record ")
    parser.add_option("-c", "--count", dest="count", 
                      type="int", default = 1,
                      help="data frame count")
    parser.add_option("-d", "--debug", dest="debug", 
                      action = "store_true", default = False,
                      help="data frame counts")
    parser.add_option("--force", dest="force", 
                      action = "store_true", default = False,
                      help="restart caculate and new the result")
    parser.add_option("-t", dest="type", 
                      default = '',
                      help="the sleep stage name [w|n1|n2|n3|n4|r|m|o]")
    
    (options, args) = parser.parse_args()

    if not options.filename: 
        print "please input filename"
        parser.print_help()
        sys.exit(1)
    if not options.signal:
        print "signal name"
        parser.print_help()
        sys.exit(1)

    if options.debug:
        import pdb
        pdb.set_trace()

    filename = options.filename 
    signal = options.signal
    record = options.record
    count = options.count
    force = options.force
    sleeptype = options.type
    
    abs_filename = os.path.join(DATA_PATH, filename)
    if not os.path.exists(abs_filename):
        print filename
        print "%s doesn't exist" % filename
    resultfiledict = checkResult(filename, signal, record, count, force, sleeptype)

    headPaser(abs_filename)
    for frame in resultfiledict:
        resultfilename = resultfiledict[frame]
        data = getrecord(abs_filename, signal, int(frame))
        if data != None:
            resultTreat(data, resultfilename)
    sys.exit(0)
    # print rec
if __name__ == '__main__':
    main()